/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.compose.ui.graphics.benchmark

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.testutils.LayeredComposeTestCase
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.PathData
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

/**
 * Generic test case for drawing a [ImageVector].
 *
 * Subclasses are responsible for providing the vector asset, so we can test and benchmark different
 * methods of loading / creating this asset.
 */
sealed class ImageVectorTestCase : LayeredComposeTestCase() {

    @Composable
    override fun MeasuredContent() {
        Box(
            Modifier.testTag(testTag)
                .size(24.dp)
                .paint(getPainter())
        )
    }

    @Composable
    override fun ContentWrappers(content: @Composable () -> Unit) {
        Box {
            content()
        }
    }

    @Composable
    abstract fun getPainter(): Painter

    abstract val testTag: String
}

/**
 * Test case that loads and parses a vector asset from an XML file.
 */
class XmlVectorTestCase : ImageVectorTestCase() {
    // TODO: should switch to async loading here, and force that to be run synchronously
    @Composable
    override fun getPainter() = painterResource(
        androidx.compose.ui.graphics.benchmark.R.drawable.ic_baseline_menu_24
    )

    override val testTag = "Xml"
}

/**
 * Test case that creates a vector asset purely from code.
 */
class ProgrammaticVectorTestCase : ImageVectorTestCase() {

    /**
     * Returns a clone of ic_baseline_menu_24 built purely in code
     */
    @Composable
    override fun getPainter() = rememberVectorPainter(
        ImageVector.Builder(
            defaultWidth = 24.dp,
            defaultHeight = 24.dp,
            viewportWidth = 24f,
            viewportHeight = 24f
        ).apply {
            addPath(
                PathData {
                    moveTo(3f, 18f)
                    horizontalLineToRelative(18f)
                    verticalLineToRelative(-2f)
                    lineTo(3f, 16f)
                    verticalLineToRelative(2f)
                    close()
                    moveTo(3f, 13f)
                    horizontalLineToRelative(18f)
                    verticalLineToRelative(-2f)
                    lineTo(3f, 11f)
                    verticalLineToRelative(2f)
                    close()
                    moveTo(3f, 6f)
                    verticalLineToRelative(2f)
                    horizontalLineToRelative(18f)
                    lineTo(21f, 6f)
                    lineTo(3f, 6f)
                    close()
                },
                fill = SolidColor(Color.Black),
                fillAlpha = 1f,
                stroke = null,
                strokeAlpha = 1f,
                strokeLineWidth = 1f,
                strokeLineCap = StrokeCap.Butt,
                strokeLineJoin = StrokeJoin.Bevel,
                strokeLineMiter = 1f
            )
        }.build()
    )

    override val testTag = "Vector"
}
